/*	File			ClientDialog.cpp
	Purpose			SIMPLE TCP CLIENT (for demonstration)
	Author			Richard Anthony	(ar26@gre.ac.uk)
	Date			December 2003
	Updated			February 2009

	Outline operation:
	The client sends a TCP connection request to the server
	Once connected, the client displays messages sent by the server
	
	This is skeletal code with no frills.
	It is intended to provide a minimalistic TCP demonstration
	(and thus hopefully is quite easy to follow).
	Students following "Systems Programming" can use this code
	as a starting point for their coursework application
*/

#include "stdafx.h"
#include "ClientDialog.h"
#include <sys/types.h>
#include <sys/timeb.h>


IMPLEMENT_DYNAMIC(CClientDialog, CDialog)
CClientDialog::CClientDialog(CWnd* pParent /*=NULL*/) // Class Constructor
	: CDialog(CClientDialog::IDD, pParent)
{	
	m_bTimerSet = false;
	client_id = 0;
}

CClientDialog::~CClientDialog() // Class Destructor
{
	Close();
}

BEGIN_MESSAGE_MAP(CClientDialog, CDialog)
	ON_WM_TIMER()	// Needed if using a timer

	// User Interface Event handlers
	ON_BN_CLICKED(IDC_CONNECT, OnBnClickedConnect)
	ON_BN_CLICKED(IDC_Disconnect, OnBnClickedDisconnect)
	ON_BN_CLICKED(IDC_BUTTON_SEND, &CClientDialog::OnBnClickedButtonSend)
	ON_BN_CLICKED(IDC_BUTTON1, &CClientDialog::OnBnClickedButton1)
END_MESSAGE_MAP()

void CClientDialog::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);

	// Map controls onto variables in the code
	DDX_Control(pDX, IDC_MESSAGE_TEXT, m_MessageText);
	DDX_Control(pDX, IDC_MESSAGE_NUMBER, m_MessageNumber);
	DDX_Control(pDX, IDC_ADD_1, m_ConnectAddress_1);
	DDX_Control(pDX, IDC_ADD_2, m_ConnectAddress_2);
	DDX_Control(pDX, IDC_ADD_3, m_ConnectAddress_3);
	DDX_Control(pDX, IDC_ADD_4, m_ConnectAddress_4);
	DDX_Control(pDX, IDC_EDIT_PORT, m_Port);
	DDX_Control(pDX, IDC_CONNECT, m_ConnectButton);
	DDX_Control(pDX, IDC_Disconnect, m_DisconnectButton);
	DDX_Control(pDX, IDCANCEL, m_CancelButton);
	DDX_Control(pDX, IDC_EDIT_SEND, m_Send);
	DDX_Control(pDX, IDC_BUTTON_SEND, m_btnSend);

	// Initialisation of User Interface controls
	m_ConnectButton.EnableWindow(true);
	m_CancelButton.EnableWindow(true);
	m_DisconnectButton.EnableWindow(false);
	m_Port.SetWindowTextA("8001");
	m_Port.EnableWindow(true);
	m_Send.EnableWindow(false);
	
	
}

IN_ADDR CClientDialog::GetConnectAddress()
{	
	IN_ADDR addr;
	CString csStr;
	m_ConnectAddress_1.GetWindowText(csStr);
	addr.S_un.S_un_b.s_b1 = (unsigned  char) atol(csStr.GetString());
	m_ConnectAddress_2.GetWindowText(csStr);
	addr.S_un.S_un_b.s_b2 = (unsigned  char) atol(csStr.GetString());
	m_ConnectAddress_3.GetWindowText(csStr);
	addr.S_un.S_un_b.s_b3 = (unsigned  char) atol(csStr.GetString());
	m_ConnectAddress_4.GetWindowText(csStr);
	addr.S_un.S_un_b.s_b4 = (unsigned  char) atol(csStr.GetString());
	return addr;
}

int CClientDialog::GetPort()
{	
	CString csStr;
	int iPort;
	m_Port.GetWindowText(csStr);
	iPort = (int) atol(csStr.GetString());
	return iPort;
}

void CClientDialog::OnBnClickedConnect() // Connect Button handler
{	
	m_iSocket = socket(AF_INET, SOCK_STREAM, PF_UNSPEC); // Create the (listen) socket
	if(INVALID_SOCKET == m_iSocket)
	{
		MessageBox("Socket create failed","Client");
		CloseAndQuit();
	}
	
	u_long lBlocking = 0;
	int iError = ioctlsocket(m_iSocket, FIONBIO, &lBlocking); // Set blocking socket behaviour
	if(SOCKET_ERROR == iError)
	{
		MessageBox("Could not set Blocking behaviour for socket","Client");
		CloseAndQuit();
	}

	m_ConnectSockAddr.sin_addr = GetConnectAddress();	// Setup Connect Address Structure
	m_ConnectSockAddr.sin_family = AF_INET;
	
	int iPort = GetPort();
	m_ConnectSockAddr.sin_port = htons(iPort);
	
	// Connect
	iError = connect(m_iSocket, (const SOCKADDR FAR*)&m_ConnectSockAddr, sizeof(m_ConnectSockAddr));
	if(SOCKET_ERROR == iError)
	{
		MessageBox("Connect failed !\n\nIs server address correct ?\nIs server running ?","Client");
		closesocket(m_iSocket);		// Close the socket
		return;
	}

	// Set socket non-blocking (now that connection established) for receiving
	u_long lNonBlocking = 1;
	iError = ioctlsocket(m_iSocket, FIONBIO, &lNonBlocking);
	if(SOCKET_ERROR == iError)
	{
		MessageBox("Could not set Non Blocking behaviour for socket","Client");
		closesocket(m_iSocket);		// Close the socket
		return;
	}
	
	DoReceive();	// 7. Enable receiving 
	m_ConnectButton.EnableWindow(false); // Update controls
	m_CancelButton.EnableWindow(false);
	m_Port.EnableWindow(false);
	m_DisconnectButton.EnableWindow(true);
	m_Send.EnableWindow(true);
	
	/*
	if(client_id != 1){
		MessageBox("k phai client dau tien","caution");
	}
	*/
	CString str_clientID;
	str_clientID.Format("%d",client_id);
	//MessageBox(str_clientID,"Client");
	//m_btnSend.EnableWindow(false);
}

void CClientDialog::InitiateTimer()
{	
	m_nTimer = SetTimer(1, 100, 0);
	m_bTimerSet = true;
}

void CClientDialog::StopTimer()
{
	if(true == m_bTimerSet)
	{
		KillTimer(m_nTimer);
		m_bTimerSet = false;
	}
}

void CClientDialog::OnTimer(UINT nIDEvent) 
{	
        DoReceive();
}

void CClientDialog::DoReceive()
{		
	StopTimer();
	int iBytesRecd;
	Message_PDU Message;

	iBytesRecd = recv(m_iSocket, (char *) &Message, sizeof(Message_PDU), 0);
	if(SOCKET_ERROR == iBytesRecd)
	{
		int iError = WSAGetLastError();
		// If no packet is queued for the socket the operation would block.
		if(iError != WSAEWOULDBLOCK)
		{	
			MessageBox("Receive failed","Client");
			CloseAndQuit();	// Simplistic - assumes connection has been lost
		}
	}
	else
	{	// Received a message
		if(Message.iMessageNumber < 0)
		{
			CloseAndQuit();	// Simplistic - assumes server has disconnected
		}
		m_MessageText.SetWindowText(Message.szText);

		// chi assign lan` dau tien khi ket noi
		if(client_id == 0){
			client_id = Message.iMessageNumber;
		}

		/*
		if(client_id == Message.message_clientID){
			if(Message.currentCanMove == true){
				m_btnSend.EnableWindow(true);				
			}else if(Message.currentCanMove == false){
				m_btnSend.EnableWindow(false);
			}
			// m_btnSend.EnableWindow(false); code cu
		}
		else if(Message.message_clientID < 0){
			//MessageBox("< 0","Client Caution");
			//m_btnSend.EnableWindow(true);
		}
		else{
			m_btnSend.EnableWindow(true);
		}
		*/

		if(Message.currentCanMove == true){
			if(client_id == Message.message_clientID){
				m_btnSend.EnableWindow(true);
			}else if(client_id != Message.message_clientID){
				m_btnSend.EnableWindow(false);
			}
		}else if(Message.currentCanMove == false){
			if(client_id == Message.message_clientID){
				m_btnSend.EnableWindow(false);
			}else if(client_id != Message.message_clientID){
				m_btnSend.EnableWindow(true);
			}
		}


		//if(Message.currentCanMove == true){
		//	MessageBox("true","can move");
		//}else if(Message.currentCanMove == false){
		//	MessageBox("false","can move");
		//}

		char szMessageNumber[15];
		_itoa_s(Message.iMessageNumber,szMessageNumber,10);
		m_MessageNumber.SetWindowText(szMessageNumber);
	}
	InitiateTimer();
}

void CClientDialog::OnBnClickedDisconnect() // Disconnect Button handler
{
	SendMessage();
	CloseAndQuit();
}

void CClientDialog::Close()
{
	shutdown(m_iSocket,2);	// Close the connection
	closesocket(m_iSocket);	// Close the socket
}

void CClientDialog::CloseAndQuit()
{
	Close();
	StopTimer();
	OnCancel();	// Exit the application
}

IN_ADDR CClientDialog::GetAddress()
{
	char szStr[200];
	DWORD lLen = sizeof(szStr);
    GetComputerNameA(szStr,&lLen);
	hostent * m_pHostent;
	m_pHostent = gethostbyname(szStr); 

	IN_ADDR addr;
	char **ppChar = m_pHostent->h_addr_list;
	char * pChar;
	if(ppChar != NULL && *ppChar != NULL)  
	{
		pChar = *ppChar; 
		addr.S_un.S_un_b.s_b1 = (unsigned  char) *pChar++;
		addr.S_un.S_un_b.s_b2 = (unsigned  char) *pChar++;
		addr.S_un.S_un_b.s_b3 = (unsigned  char) *pChar++;
		addr.S_un.S_un_b.s_b4 = (unsigned  char) *pChar;
	}
	else
	{
		addr.S_un.S_addr = -1;	// signal error
	}
	return addr;
}

void CClientDialog::SendMessage() // Send a simple message to all connected clients
{
	Message_PDU Message;
	strcpy_s(Message.szText,"_Disconnect");
	DoSend(Message);
}

void CClientDialog::DoSend(Message_PDU Message) // The actual send
{	
	int iBytesSent;
	iBytesSent = send(m_iSocket, (char *) &Message, sizeof(Message_PDU), 0);
	if(SOCKET_ERROR == iBytesSent)
	{
		MessageBox("Failed to send","Client");
	}
}
void CClientDialog::OnBnClickedButtonSend()
{
	Message_PDU Message;
	m_Send.GetWindowTextA(Message.szText,MAX_MESSAGE_LENGTH);
	Message.message_clientID = client_id;
	DoSend(Message);
}


void CClientDialog::OnBnClickedButton1()
{
	// show client id
	//char str[10];
	//itoa(m_iMessageCount, str, 10);
	
	CString str_clientID;
	str_clientID.Format("%d",client_id);
	MessageBox(str_clientID,"Client");
}
